﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using WyUnity.Data.DataAccess;
using WyUnity.Utility;

namespace WyUnity.Data.Query
{
	public class Columns : IDictionary<string, object>
	{
		public Columns() { }

		private readonly List<NameValue> _list = new List<NameValue>();
		/// <summary>
		/// 增加一个更新字段(Common内部)
		/// </summary>
		public void Add(string field, object value)
		{
			if (value != null && value.GetType() == typeof(DateTime) && (DateTime)value == DateTime.MinValue)
				value = Util.DbMinDate;

			_list.Add(new NameValue { Field = field, Value = value });
		}
		/// <summary>
		/// 当前字段个数
		/// </summary>
		public int FieldCount { get { return _list.Count; } }
		/// <summary>
		/// 生成更新SQL片段
		/// </summary>
		public string ToInsertFieldSql()
		{
			if (_list.Count == 0) throw new Exception("没有字段可以插入");
			return _list.Aggregate(string.Empty, (s, e) => s + string.Format(",[{0}]", (object)e.Field)).Substring(1);
		}
		/// <summary>
		/// 生成更新SQL片段
		/// </summary>
		public string ToInsertValueSql(ISqlDialect dialect, out DbParameter[] ps)
		{
			if (_list.Count == 0) throw new Exception("没有字段可以插入");

			var p = new ParameterProvider(dialect, "I");

			var r = _list.Aggregate(string.Empty, (s, e) => s + string.Format(",{0}", p.CreateOne(e.Value))).Substring(1);
			ps = p.GetParams();
			return r;
		}

		/// <summary>
		/// 生成更新SQL片段
		/// </summary>
		internal string ToUpdateSql(ISqlDialect dialect, out DbParameter[] ps)
		{
			if (_list.Count == 0) throw new Exception("没有字段可以更新");

			var p = new ParameterProvider(dialect, "U");
			var r = _list.Aggregate(string.Empty, (s, e) => s + string.Format(",[{0}]={1}", e.Field, p.CreateOne(e.Value))).Substring(1);
			ps = p.GetParams();
			return r;
		}

		/// <summary>
		/// 从更新列表中移除制定的字段
		/// </summary>
		public void RemoveFields(List<string> fields)
		{
			_list.RemoveAll(f => fields.Contains(f.Field));
		}

		public bool Remove(string p)
		{
			return _list.RemoveAll(f => f.Field == p) > 0;
		}


		public bool ContainsKey(string key)
		{
			return _list.Any(f => f.Field == key);
		}

		public ICollection<string> Keys
		{
			get
			{
				return _list.Aggregate(new List<string>(), (s, a) =>
															{
																s.Add(a.Field);
																return s;
															});
			}
		}

		public bool TryGetValue(string key, out object value)
		{
			var v = _list.FirstOrDefault(f => f.Field == key);
			value = v == null ? null : v.Value;
			return v != null;
		}

		public ICollection<object> Values
		{
			get
			{
				return _list.Aggregate(new List<object>(), (s, a) =>
				{
					s.Add(a.Value);
					return s;
				});
			}
		}

		public object this[string key]
		{
			get
			{
				object v;
				TryGetValue(key, out v);
				return v;
			}
			set
			{
				if (ContainsKey(key))
				{
					var v = _list.FirstOrDefault(f => f.Field == key);
					v.Value = value;
				}
				else
					Add(key, value);
			}
		}

		public void Add(KeyValuePair<string, object> item)
		{
			Add(item.Key, item.Value);
		}

		public void Clear()
		{
			_list.Clear();
		}

		public bool Contains(KeyValuePair<string, object> item)
		{
			return ContainsKey(item.Key);
		}

		public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
		{
			throw new NotImplementedException();
		}

		public int Count
		{
			get { return FieldCount; }
		}

		public bool IsReadOnly
		{
			get { return false; }
		}

		public bool Remove(KeyValuePair<string, object> item)
		{
			return Remove(item.Key);
		}

		public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
		{
			foreach (var item in _list)
			{
				yield return new KeyValuePair<string, object>(item.Field, item.Value);
			}
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return _list.GetEnumerator();
		}
	}
}
